home *** CD-ROM | disk | FTP | other *** search
- TITLE MISCMATH - VARIOUS MATH IN ASSEMBLER
-
- COMMENT $
-
- // Routines to do various math that can't be done in C.
- // Some are just for efficiency, and could be done in C with
- // a true 32-bit compiler. Others use 64-bit intermediate results.
-
- // All code by Dave Stampe, last updated 23/12/93
-
- /*
- This code is part of the VR-386 project, created by Dave Stampe.
- VR-386 is a desendent of REND386, created by Dave Stampe and
- Bernie Roehl. Almost all the code has been rewritten by Dave
- Stampre for VR-386.
-
- Copyright (c) 1994 by Dave Stampe:
- May be freely used to write software for release into the public domain
- or for educational use; all commercial endeavours MUST contact Dave Stampe
- (dstampe@psych.toronto.edu) for permission to incorporate any part of
- this software or source code into their products! Usually there is no
- charge for under 50-100 items for low-cost or shareware products, and terms
- are reasonable. Any royalties are used for development, so equipment is
- often acceptable payment.
-
- ATTRIBUTION: If you use any part of this source code or the libraries
- in your projects, you must give attribution to VR-386 and Dave Stampe,
- and any other authors in your documentation, source code, and at startup
- of your program. Let's keep the freeware ball rolling!
-
- DEVELOPMENT: VR-386 is a effort to develop the process started by
- REND386, improving programmer access by rewriting the code and supplying
- a standard API. If you write improvements, add new functions rather
- than rewriting current functions. This will make it possible to
- include you improved code in the next API release. YOU can help advance
- VR-386. Comments on the API are welcome.
-
- CONTACT: dstampe@psych.toronto.edu
- */
- $
-
- .MODEL large
-
- ; # define XFSC 536870912 /* 2**29 for shifting xform coeffs to long */
-
-
- .DATA
-
- _longmath_overflow dd 0 ;; overflow/high dword return
-
- .CODE INTMATH
-
-
- MULT29 MACRO a,b ; multiply <3.29> -> eax
- mov eax,DWORD PTR a
- imul DWORD PTR b
- shrd eax,edx,29
- adc eax,0
- ENDM
-
- MMULT29 MACRO a,b,c ; multiply 3 of <3.29> -> eax
- mov eax,DWORD PTR a
- imul DWORD PTR b
- shrd eax,edx,29
- adc eax,0
- imul DWORD PTR c
- shrd eax,edx,29
- adc eax,0
- ENDM
-
- DOTPROD MACRO a,b,c,x,y,z,p ; dot product plus p, accum in ecx:ebx
- mov eax,a ; result in eax
- imul DWORD PTR x
- mov ecx,edx
- mov ebx,eax
- mov eax,b
- imul DWORD PTR y
- add ebx,eax
- adc ecx,edx
- mov eax,c
- imul DWORD PTR z
- add eax,ebx
- adc edx,ecx
- shrd eax,edx,29
- adc eax,p
- ENDM
-
- ;/****************** MISC. MATH SUPPORT **********/
-
-
-
- ;long m_mult(long a, long b) /* perform mult. by matrix element */
- ;{ /* where either a or b is in <3.29> format */
-
- a equ [bp+8] ; arguments
- b equ [bp+12]
-
- PUBLIC _m_mult
-
- _m_mult proc far
-
- .386
- push ebp
- mov ebp,esp
-
- MULT29 a,b
-
- shld edx,eax,16 ; return in dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _m_mult endp
-
-
- ;long m2_mult(long a, long b, long c) /* perform mult. by matrix element */
- ;{ /* where a and b is in <3.29> format */
-
- a equ [bp+8] ; arguments
- b equ [bp+12]
- b equ [bp+16]
-
- PUBLIC _m_mult
-
- _m2_mult proc far
-
- .386
- push ebp
- mov ebp,esp
-
- MMULT29 a,b,c
-
- shld edx,eax,16 ; return in dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _m2_mult endp
-
-
-
-
- ;long divide_29(long a, long b) /* perform divide, result in <3.29> format */
- ;{ /* up to user to test for overflow */
-
- a equ DWORD PTR [bp+8] ; arguments
- b equ DWORD PTR [bp+12]
-
- PUBLIC _divide_29
-
- _divide_29 proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov eax,a
- cdq
- shld edx,eax,29
- shl eax,29
-
- idiv b
-
- shld edx,eax,16 ; return in dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _divide_29 endp
-
-
- ;long divide_long(long ahi, long alo, long b)
-
- a equ DWORD PTR [bp+8] ; arguments
- b equ DWORD PTR [bp+12]
- b equ DWORD PTR [bp+16]
-
- PUBLIC _divide_long
-
- _divide_long proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov eax,alo
- mov edx,ahi
-
- idiv b
- mov _longmath_overflow,edx
-
- shld edx,eax,16 ; return in dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _divide_long endp
-
-
- ;long mult_long(long a, long b) /* perform multiply on longs */
-
- a equ DWORD PTR [bp+8] ; arguments
- b equ DWORD PTR [bp+12]
-
- PUBLIC _mult_long
-
- _mult_long proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov eax,a
- imul b
- mov _longmath_overflow,edx
-
- shld edx,eax,16 ; return in dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _mult_long endp
-
-
-
- ; // shifts 32-bit signed number left or right (>0 is left, <0 is right)
- ;extern long_shift32(long a, int shift);
-
- a equ DWORD PTR [bp+8] ; arguments
- shift equ WORD PTR [bp+12]
-
- PUBLIC _long_shift32
-
- _long_shift32 proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov eax,a
- cdq
- mov cx,shift
- or cx,cx
- jge left_shift32
-
- neg cx
- shrd eax,edx,cl
- shr edx,cl
- adc eax,0
- adc edx,0
- mov _longmath_overflow,edx
- jmp done_shift32
-
- left_shift32:
- shld edx,eax,cl
- shl eax,cl
- mov _longmath_overflow,edx
-
- done_shift32:
- shld edx,eax,16 ; return in dx:ax and eax
-
- mov esp,ebp
- pop ebp
- ret
-
- _long_shift32 endp
-
-
-
-
- ; // shifts 64-bit signed number left or right (>0 is left, <0 is right)
- ; // msdword of result is returned in longmath_overflow
- ;extern long_shift64(long ahi, long alo, int shift);
-
- ahi equ DWORD PTR [bp+8] ; arguments
- alo equ DWORD PTR [bp+12]
- shift equ WORD PTR [bp+16]
-
- PUBLIC _long_shift64
-
- _long_shift64 proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov edx,ahi
- mov eax,alo
- mov cx,shift
- or cx,cx
- jge left_shift64
-
- neg cx
- shrd eax,edx,cl
- shr edx,cl
- adc eax,0
- adc edx,0
- mov _longmath_overflow,edx
- jmp done_shift64
-
- left_shift64:
- shld edx,eax,cl
- shl eax,cl
- mov _longmath_overflow,edx
-
- done_shift64:
- shld edx,eax,16 ; return in dx:ax and eax
-
- mov esp,ebp
- pop ebp
- ret
-
- _long_shift64 endp
-
-
-
- ;long mulmuldiv(long a, long b) /* perform (a*b)/c with 64-bit intermediate */
- ;{ /* up to user to test for overflow */
-
- a equ DWORD PTR [bp+8] ; arguments
- b equ DWORD PTR [bp+12]
- c equ DWORD PTR [bp+16]
-
- PUBLIC _mulmuldiv
-
- _mulmuldiv proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov eax,a
- imul b
- idiv c
- mov _longmath_overflow,edx
-
- shld edx,eax,16 ; return in dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _mulmuldiv endp
-
-
-
- ;long dot_prod_29(long a, long b, long c, long x, long y, long z)
- ; /* computes (Ax + By + Cz)>>29 */
-
- a equ [bp+8] ; arguments
- b equ [bp+12]
- c equ [bp+16]
- x equ [bp+20]
- y equ [bp+24]
- z equ [bp+28]
-
- PUBLIC _dot_prod_29
-
- _dot_prod_29 proc far
-
- .386
- push ebp
- mov ebp,esp
-
- push esi
- push edi
- push ecx
-
- DOTPROD a,b,c,x,y,z,0
-
- shld edx,eax,16 ; return dx:ax
-
- pop edi
- pop esi
-
- mov esp,ebp
- pop ebp
- ret
-
- _dot_prod_29 endp
-
-
-
- ;long scale_16(long s, long a, long x) /* perform scaling by 16.16 number */
-
-
- s equ [bp+8] ; arguments
- a equ [bp+12]
- x equ [bp+16]
-
- PUBLIC _scale_16
-
- _scale_16 proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov eax,DWORD PTR x
- add eax,DWORD PTR a
- imul DWORD PTR s
- shrd eax,edx,16
- adc eax,0
-
- shld edx,eax,16 ; return in eax and dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _scale_16 endp
-
-
- ;long calc_scale_16(long a, long b, long s) /* compute 16.16 scaling factor */
-
- a equ [bp+8] ; arguments
- b equ [bp+12]
- s equ [bp+16]
-
- PUBLIC _calc_scale_16
-
- _calc_scale_16 proc far
-
- .386
- push ebp
- mov ebp,esp
-
- xor eax,eax ; return 0 for divide error
- mov ebx,DWORD PTR a
- sub ebx,DWORD PTR b
- je cdiv
- mov eax, DWORD PTR s
- cdq
- shld edx,eax,17
- shl eax,17
- idiv ebx
- cdiv:
- shld edx,eax,16 ; return in eax and dx:ax
-
- mov esp,ebp
- pop ebp
- ret
-
- _calc_scale_16 endp
-
-
-
-
-
-
- ;long plane_y(long a, long b, long c, long d, long x, long z)
- ; /* used to compute floor/ceiling of areas */
-
- a equ [bp+8] ; arguments
- b equ [bp+12]
- c equ [bp+16]
- d equ [bp+20]
- x equ [bp+24]
- z equ [bp+28]
-
- PUBLIC _plane_y
-
- _plane_y proc far
-
- .386
- push ebp
- mov ebp,esp
- ;* computes (Ax + Cz + D)/-B */
- push esi
- push edi
-
- xor eax,eax
- test DWORD PTR b,-1
- je divzero
-
- mov eax,a
- imul DWORD PTR x
- mov esi,eax
- mov edi,edx
-
- mov eax,c
- imul DWORD PTR z
- add esi,eax
- adc edi,edx
-
- mov eax,DWORD PTR d
- cdq
- add eax,esi
- adc edx,edi
- idiv DWORD PTR b
- divzero:
- shld edx,eax,16 ; return in eax and dx:ax
- pop edi
- pop esi
-
- mov esp,ebp
- pop ebp
- ret
-
- _plane_y endp
-
-
-
-
- ;/************* 32 BIT CITY-BLOCK DISTANCE *************/
-
- ;/* returns abs(x1-x2) + abs(y1-y2) + abs(z1-z2) */
-
- ;long big_dist(long x1, long y1, long z1,
- ; long x2, long y2, long z2 )
-
- x1 equ [bp+8] ; arguments
- y1 equ [bp+12]
- z1 equ [bp+16]
- x2 equ [bp+20]
- y2 equ [bp+24]
- z2 equ [bp+28]
-
- PUBLIC _big_dist
-
- _big_dist proc far
-
- .386
- push ebp
- mov ebp,esp
-
- push ecx
-
- mov eax,x1
- sub eax,x2
- cdq
- xor eax,edx
- sub eax,edx
- mov ecx,eax
-
- mov eax,y1
- sub eax,y2
- cdq
- xor eax,edx
- sub eax,edx
- add ecx,eax
-
- mov eax,z1
- sub eax,z2
- cdq
- xor eax,edx
- sub eax,edx
- add eax,ecx
-
- shld edx,eax,16 ; return in eax and dx:ax
-
- pop ecx
-
- mov esp,ebp
- pop ebp
- ret
-
- _big_dist endp
-
-
-
-
- end
-
-
-